﻿using System.ComponentModel;
using System;
namespace DeepEarth.Map.Core.Tiling
{
    [TypeConverter(typeof(MapModeTypeConverter))]
    public class MapMode
    {
        /// <summary>
        /// A map mode identifier. Is used as a key in the UI (XAML) and to identify the map mode.
        /// </summary>
        /// <remarks>
        /// In the following line the "PhotoMap" is a map mode key and it is an Identifier for the map mode.
        /// <example>
        /// &lt;nearmap:NearMapTileOverlay Mode="PhotoMap" /&gt;
        /// </example>
        /// </remarks>
        public string Identifier { get; private set; }

        /// <summary>
        /// A mode name.
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// Determines the map mode provider.
        /// </summary>
        /// <remarks>
        /// Required to be unique. Can be used as a convention key, for example, when displaying an icon for the mode.
        /// </remarks>
        public string ProviderId { get; private set; }

        /// <summary>
        /// The key for the provider. Provider uses it to build URL.
        /// </summary>
        public string ProviderKey { get; private set; }

        /// <summary>
        /// Determines if the mode is a "servide mode".
        /// </summary>
        /// <remarks>
        /// Some of the map modes are just "overlay" modes, and it does'n male sense to let users to 
        /// select them as a "main" map mode. For example, the NearMap's StreetOverlay mode 
        /// is meant to be used as an overlay on the "real" map mode (PhotoMap), so it is just an "overlay" mode.
        /// User may be able to select it as an additional mode, but not as a standalone one.
        /// </remarks>
        public bool IsOverlayTileSource { get; private set; }

        public bool HasLabels { get; private set; }
        public bool HasDates { get; private set; }

        /// <summary>
        /// The desired order, it is useful when several overlay maps are composed.
        /// The default value is 1.
        /// </summary>
        /// <remarks>
        /// For example, if we have two overlays on top of PhotoMap: streets and terrain, it is probably useful to always have streets on top of terrain.
        /// </remarks>
        [DefaultValue(1)]
        public int Order { get; private set; }

        public MapMode(string providerId, string providerKey, string identifier, string name, int order)
            : this(providerId, providerKey, identifier, name, order, false, false, false)
        {
        }

        public MapMode(string providerId, string providerKey, string identifier, string name)
            : this(providerId, providerKey, identifier, name, 1, false, false, false)
        {
        }

        public MapMode(string providerId, string providerKey, string identifier, string name, int order, bool isOverlayTileSource, bool hasLabels, bool hasDates)
        {
            if (String.IsNullOrEmpty(providerId)) throw new ArgumentNullException("providerId");
            if (String.IsNullOrEmpty(providerKey)) throw new ArgumentNullException("providerKey");
            if (String.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier");

            ProviderId = providerId;
            ProviderKey = providerKey;
            Identifier = identifier;
            Name = name;
            IsOverlayTileSource = isOverlayTileSource;
            HasLabels = hasLabels;
            HasDates = hasDates;
            Order = order;
        }

        public override bool Equals(object obj)
        {
            if (obj is MapMode) return ((MapMode)obj) == this;
            return false;
        }

        public override int GetHashCode()
        {
            return String.Concat(ProviderKey, "$_$", Identifier).GetHashCode();
        }

        public static bool operator ==(MapMode thisMode, MapMode otherMode)
        {
            if (thisMode == (object)null && otherMode == (object)null) return true;
            if (thisMode == (object)null || otherMode == (object)null) return false;

            return thisMode.ProviderKey == otherMode.ProviderKey && thisMode.Identifier == otherMode.Identifier;
        }

        public static bool operator !=(MapMode thisMode, MapMode otherMode)
        {
            return !(thisMode == otherMode);
        }
    }
}
